<?php
/**
 * HTML 编辑器
 * User: apple
 * Date: 1/23/22
 * Time: 9:54 PM
 */

use app\assets\BackendAsset as Asset;

/* @var $this yii\web\View */
/* @var $_params_ array 总参数变量 */
/* @var $scenario array 图片上传场景 */
/* @var $width string | integer 编辑器宽度 */
/* @var $height array 编辑器高度 */
/* @var $autoInit bool 是否自动初始化编辑器 */
/* @var $code string 初始内容 */
/* @var $localImg bool 图片是否本地化 */
/* @var $prefix string 前缀(主要用作VUE列表渲染) */
/* @var $suffix string 后缀(主要用作VUE列表渲染) */

// 是否调试模式
$debugger = YII_DEBUG ? 'true' : 'false';
// 前缀
$prefix = empty($prefix) ? 'html_editor' : $prefix;
// 后缀
$suffix = empty($suffix) ? "''" : $suffix;

// 编辑器宽度
$width = empty($width) || (!is_numeric($width) && !strstr($width, '%')) ? 300 : $width;
// 编辑器高度
$height = empty($height) || !is_numeric($height) ? 300 : $height;

// 编辑器 默认内容
$code = empty($code) ? 'null' : $code;

// 图片本地化
$localImg = !empty($localImg) && $localImg ? 'true' : 'false';
$localImg = false; // 全部不本地化

// 代码编辑器
$codeEditor = $this->render('./code-editor.php', [
    'height' => $height,
    'width'  => $width,
]);

// 是否自动初始化编辑器
$autoInit = !isset($autoInit) ? true : $autoInit;

// HTML
$template = <<<EOL

<div>
    <div :id="editorId" element-loading-text="操作中..." v-loading.lock="doing" style="width: $width"></div>
    
    <!--黏贴用暂存HTML  开始-->
    <div style="display: none;" :id="editorStageId"></div>
    <!--黏贴用暂存HTML  结束-->
    
    <!--代码编辑器HTML 开始-->
    <el-dialog title="编辑器赋值" :visible.sync="showCodeDialog" class="dialog-medium body-nop"
        :lock-scroll="true" width="80%" :close-on-click-modal="false"
        append-to-body modal-append-to-body>
    
        {$codeEditor}
        
        <div slot="footer">
            <el-button type="danger" size="mini" @click="showCodeDialog = false">取消</el-button>
            <el-button size="mini" type="primary" @click="codeEditorUpdateContent()">
                保存
            </el-button>
        </div>
    </el-dialog>
    <!--代码编辑器HTML 结束-->
</div>

EOL;

$js = <<<EOL
Vue.component('editor', {
    template: `$template`,
    props: {
        column: { // 绑定字段
            type: String,
            default: ''
        },
        height: { // 高度
            type: String,
            default: '500px'
        },
        code: { // 编辑器内容
            type: String,
            default: ''
        },
        suffix: { // 后缀传入 - 给代码编辑器用
            type: String,
            default: ''
        }
    },
    data: function () {
        return {
            setting: {
                maxFileSize: 2097152, // 文件大小2m
                fileTypeList: [
                    'image/jpg',
                    'image/jpeg',
                    'image/png',
                    'image/gif',
                ], // 文件类型
                defaultImgPath: '', // 默认图
            },
            editorId: '{$prefix}_' + \$w.getRandStr(),
            editorStageId: '{$prefix}_stage_' + \$w.getRandStr(),
            showError: {$debugger}, // 是否展示错误
            editor: null, // UE编辑器
            doing: false, // 编辑器状态
            showCodeDialog: false, // 是否展示[CODE]编辑器窗口
        };
    },
    created: function () {
        
        var that = this;
        this.\$nextTick(function () {
        
EOL;
if ($autoInit) {
    $js .= <<<EOL

            // 初始化
            that.initEditor(that.code);
            
EOL;
}
$js .= <<<EOL

        });
    },
    methods: {
        /**
         * 初始化编辑器
         * @param \$htmlCode
         */
        initEditor: function (\$htmlCode) {
        
            if (this.editor) return false;
            // 默认值
            \$htmlCode = \$htmlCode || '';
            
            // 初始化UE
            var Wang = window.wangEditor;
            this.editor = new Wang('#' + this.editorId);
            


            // 自定义[z-index]
            this.editor.config.zIndex = 500;
            // 编辑器高度
            this.editor.config.height = '$height';
            this.editor.config.width = '$width';
            // 菜单
            this.editor.config.menus = [
                "head",
                "bold",
                "fontSize",
                "fontName",
                "italic",
                "underline",
                "strikeThrough",
                "indent",
                "lineHeight",
                "foreColor",
                "backColor",
                "link",
                "list",
                "justify",
                "quote",
                "emoticon",
                "image",
                "video",
                "table",
                "code",
                "splitLine",
                "undo",
                "redo"
            ];
            // 配置 server 接口地址
            this.editor.config.uploadImgServer = \$w.getApiUrl('upload');
            // 自定义上传参数
            this.editor.config.uploadImgParams = {
                scenario: '$scenario', // 场景
            };
            // 图片 上传文件名
            this.editor.config.uploadFileName = 'files';
            // 图片 自定义上传回调
            this.editor.config.uploadImgHooks = {
                // 图片上传并返回了结果，想要自己把图片插入到编辑器中
                // 例如服务器端返回的不是 { errno: 0, data: [...] } 这种格式，可使用 customInsert
                customInsert: this.insertImgHandle
            };
            // 插入网络图片的回调
            // this.editor.config.linkImgCallback = this.upRemoteImgHandle;
            // 配置粘贴文本的内容处理 -- todo:暂时关闭远程图上传
            // this.editor.config.pasteTextHandle = this.pasteContentHandle;
            // // 默认情况下，显示所有菜单
            var that = this;
            var HtmlButton = function (\$editor) {
                this.editor = \$editor;
                this.\$elem = Wang.$(
                    '<div class="w-e-menu">' +
                    '    <i class="w-icon-html" style="font-size:24px"></i>' +
                    '</div>'
                );
                this.type = 'click';
                this._active = false;
                this.isActive = false;
                var editorInstance = this;
                this.\$elem.on('click', function (\$event) {
                    // editorInstance.clickHandler(\$event, editorInstance);
                    // 展示赋值[HTML]窗口
                    that.showCodeDialog = true;
                    // 初始化代码编辑器
                    that.\$nextTick(function () {
                        // 初始化
                        if (!that.\$refs['code_html_editor']) return that.\$message({
                            type: 'error',
                            showClose: true,
                            message: '找不到代码编辑器实例！'
                        });
                        // 赋值内容
                        that.\$refs['code_html_editor'].codeEditorSetContent(that.getEditorHtml());
                    });
                });
            };
            HtmlButton.prototype = {
                constructor: HtmlButton,
                clickHandler: function (\$event, \$self) {
                    // 激活菜单
                    // 1. 菜单 DOM 节点会增加一个 .w-e-active 的 css class
                    if (this._active === true) {
                        this.unActive();
                    }
                    // 取消激活菜单
                    // 1. 菜单 DOM 节点会删掉 .w-e-active
                    else if (this._active === false) {
                        this.active();
                    }
                },
                /**
                 * 尝试改变菜单状态
                 * 实际效果是点击内容
                 */
                tryChangeActive: function () {

                },
                /**
                 * 菜单激活状态
                 */
                active: function () {
                    this._active = true;
                    this.\$elem.addClass('w-e-active');
                },
                /**
                 * 菜单取消激活状态
                 */
                unActive: function () {
                    this._active = false;
                    this.\$elem.removeClass('w-e-active')
                }
            };
            this.editor.menus.extend("html", HtmlButton);
            this.editor.config.menus.push('html');
            
            // 创建实例
            this.editor.create();
            
            // 默认赋值
            if (!\$w.isEmpty(\$htmlCode)) this.editor.txt.html(\$htmlCode);
            
            return this.editor;
        },
        /**
         * 销毁实例
         */
        destroyEditor: function () {
        
            if (!this.editor) return true;
            
            // 删除实例对象值
            this.\$set(this, 'editor', null);
        },
        /**
         * 获取编辑器[HTML]内容
         */
        getEditorHtml: function () {
            
            if (!this.editor) return '';
            
            return this.editor.txt.html();
        },
        /**
         * 获取编辑器[TEXT]内容
         */
        getEditorText: function () {
            
            if (!this.editor) return '';
            
            return this.editor.txt.text();
        },
        /**
         * 编辑器内容 追加(最后)
         */
        editorAppendContent: function (\$content) {
            this.editor.txt.html(this.getEditorHtml() + \$content)
        },
        /**
         * 编辑器内容 覆盖
         */
        editorSetContent: function (\$content) {
            
            this.editor.txt.html(\$content);
        },
        /**
         * [编辑器]黏贴内容处理编辑器追加内容
         * @param \$pasteStr
         * @returns {*}
         */
        pasteContentHandle: function (\$pasteStr) {
        
            // 暂存容器中赋值
            var stageDom = $('#' + this.editorStageId);
            stageDom.html(\$pasteStr);

            var imgDomLength = stageDom.find('img').length;
            // 无图直接黏贴成功 - 返回内容
            if (!imgDomLength || imgDomLength.length < 1) return \$pasteStr;
            
            var item, isUploaded, imgSrcList = [];
            for (var i = 0; i < imgDomLength; i++) {
                // 当前图片条目
                item = stageDom.find('img').eq(i);
                
                // 添加到图片地址列表 - 取出备份地址
                imgSrcList.push(item.attr('src'));
            }
            
            var that = this;
            that.\$nextTick(function () {
                // 上传图
                if ('$localImg' === 'true') that.upRemoteImgHandle(imgSrcList);
            });
            
            return \$pasteStr;
        },
        /**
         * 获取代码编辑器 提交到文本编辑内容
         */
        codeEditorUpdateContent: function () {
        
            // 代码编辑器内容
            var codeContent = this.\$refs['code_html_editor'].getCodeEditorValue();
            // 文本编辑器内容清空-为了迎合直接黏贴进编辑器中逻辑[pasteContentHandle]方法
            this.editorSetContent(codeContent);
            // 关闭弹出层
            this.showCodeDialog = false;
            // 远程抓图
            this.pasteContentHandle(codeContent);
        },
        /**
         * [编辑器]自定义上传图片
         * @param \$insertImgFn
         * @param \$result
         */
        insertImgHandle: function (\$insertImgFn, \$result) {
            // 返回状态非成功
            if (parseInt(\$result.no) !== 200) {
                return this.\$message({
                    type: 'error',
                    showClose: true,
                    message: \$result.msg
                });
            }
            // 返回图片状态非成功
            if (\$result.data.state !== 'SUCCESS') {
                if (this.showError) console.error('单张图片上传失败：' + \$result.data.error_hint);
                return this.\$message({
                    type: 'error',
                    showClose: true,
                    message: '上传失败'
                });
            }
            return \$insertImgFn(\$result.data.path, {'data-is-uploaded': '1'});
        },
        /**
         * [编辑器]上传远程图片
         * @param \$src
         */
        upRemoteImgHandle: function (\$src) {

            // 图片上传
            if (!\$src || \$src.length < 1) {
                if (this.showError) console.error('图片信息不存在: ', \$src);
                return this.\$message({
                    type: 'warning',
                    showClose: true,
                    message: '上传失败'
                });
            }
            
            if (!(\$src instanceof Array)) {
                \$src = [\$src];
            }
            
            // 暂存容器中赋值
            var stageDom = $('#' + this.editorStageId);
            stageDom.html(this.getEditorHtml());
            
            // 是否已经上传 - 过滤
            var imageList = [];
            for (item of \$src) {
            
                var itemDom = stageDom.find('img[src="' + item + '"]');
                // 已下载
                var isUploaded = itemDom.data('is-uploaded');
                if (isUploaded && parseInt(isUploaded) === 1) continue;
                
                // 下载中
                var isUploading = itemDom.data('is-uploading');
                if (isUploading && parseInt(isUploading) === 1) continue;
                
                // 图片图片地地址备份
                itemDom.attr('_src', itemDom.attr('src'));
                // 图片改为正在加载图
                itemDom.attr('src', this.setting.default_img_path);
                
                imageList.push(item);
            }
            
            // 是空的略过
            if (\$w.isEmpty(imageList)) return false;
            
            
            // 编辑器状态 使用中...
            this.doing = true;
            
            var that = this;
            $.ajax({
                url: \$w.getApiUrl('uploadRemoteImg'),
                type: 'POST',
                data: {
                    source: imageList,
                    scenario: '$scenario'
                },
                dataType: "json",
                success: function (event) {

                    that.\$nextTick(function () {
                        // 编辑器状态 未使用中...
                        that.doing = false;
                    });
                    // 必须先登录
                    if (parseInt(event.no) === 401) {

                        that.\$message({
                            type: 'warning',
                            showClose: true,
                            message: '登录超时，请重新登录'
                        });

                        // 几秒之后移除
                        return setTimeout(function () {
                            window.parent.location.href = \$w.getPageUrl('login');
                        }, 810);
                    }

                    // 操作失败显示错误信息
                    if (parseInt(event.no) !== 200) {

                        // 应该赋值到错误图片路径
                        return that.\$message({
                            type: 'error',
                            showClose: true,
                            message: event.msg
                        });
                    }

                    var item, imgDomItem = [], count = 1, errorTitle = [];
                    for (var i in event.data) {
                        if (!event.data.hasOwnProperty(i)) continue;
                        // 当前上传返回图片条目
                        item = event.data[i];
                        // 当前操作图片[dom]
                        imgDomItem = stageDom.find('img[_src="' + item['source'] + '"]');
                        
                        // 是否已上传标记 - 改为是
                        imgDomItem.attr('data-is-uploaded', 1);
                        // 图片 替换为已上传图
                        imgDomItem.attr('src', item['path']);
                        // 图片 增加[alt]属性
                        imgDomItem.attr('alt', '');

                        // 此次是未成功 提醒下
                        if (item['state'] !== 'SUCCESS') errorTitle.push(count);
                        count++;
                    }

                    // 有错误信息
                    if (errorTitle && errorTitle.length > 0) {
                        that.\$message({
                            type: 'warning',
                            showClose: true,
                            message: '第' + errorTitle.join('、') + '张图片上传失败，请注意检查'
                        });
                    }
                    // 最终再付给编辑器
                    that.editor.txt.html(stageDom.html());
                },
                error: function (event) {

                    return that.\$message({
                        type: 'error',
                        showClose: true,
                        message: '操作频繁，请稍后尝试'
                    });
                }
            });
        },
    }
});
EOL;
if (empty($this->params['reg_html_editor'])) Asset::addScript($this, '/plugin/wangeditor/js/wangEditor.min.js');
if (empty($this->params['reg_html_editor'])) $this->registerJs($js);
// 已注册过
$this->params['reg_html_editor'] = true;

echo "<editor height='$height' :code='$code' :suffix=\"$suffix\" :ref=\"'{$prefix}' + $suffix\"></editor>";
?>
